package gbackup.core;

import gbackup.error.NoSuchDirectoryException;
import gbackup.error.NoSuchFileException;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URL;
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import com.google.gdata.client.docs.DocsService;
import com.google.gdata.data.docs.DocumentListFeed;

public class Utility {
	public static DocumentListFeed getDocumentListFeedByURL(DocsService client, String url) {
		try {
			URL feedUri = new URL(url);
			DocumentListFeed feed = client.getFeed(feedUri, DocumentListFeed.class);
			return feed;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static java.io.File unzip(java.io.File sourceFile) {
		final int BUFFER = 2048;
		try {
			java.io.File tmpFile = java.io.File.createTempFile("tmp_", ".zip");
			BufferedOutputStream dest = null;
			FileInputStream fis = new FileInputStream(sourceFile);
			ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
			ZipEntry entry = null;
			while ((entry = zis.getNextEntry()) != null) {
				int count;
				byte data[] = new byte[BUFFER];

				FileOutputStream fos = new FileOutputStream(tmpFile);
				dest = new BufferedOutputStream(fos, BUFFER);
				while ((count = zis.read(data, 0, BUFFER)) != -1) {
					dest.write(data, 0, count);
				}
				dest.flush();
				dest.close();
			}
			zis.close();

			tmpFile.deleteOnExit();
			return tmpFile;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	public static java.io.File zip(java.io.File sourceFile) {
		final int BUFFER = 2048;
		try {
			java.io.File tmpFile = java.io.File.createTempFile("tmp_", ".zip");
			BufferedInputStream origin = null;
			FileOutputStream dest = new FileOutputStream(tmpFile);
			ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
			// out.setMethod(ZipOutputStream.DEFLATED);
			byte data[] = new byte[BUFFER];

			FileInputStream fi = new FileInputStream(sourceFile.getAbsolutePath());
			origin = new BufferedInputStream(fi, BUFFER);
			ZipEntry entry = new ZipEntry(sourceFile.getName());
			out.putNextEntry(entry);
			int count;
			while ((count = origin.read(data, 0, BUFFER)) != -1) {
				out.write(data, 0, count);
			}
			origin.close();
			out.close();

			tmpFile.deleteOnExit();
			return tmpFile;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	/* TODO: Bad idea to put here */
	public static java.io.File getFileByPath(java.io.File rootDirectory, java.io.File currentDirectory, String path) throws NoSuchFileException {
		try {
			java.io.File targetFile = Utility._getFileByPath(rootDirectory, currentDirectory, path);
			if (!targetFile.isFile())
				throw new NoSuchFileException(path);
			return targetFile;
		} catch (NoSuchFileException nsfe) {
			throw new NoSuchFileException(path);
		}
	}

	public static java.io.File getDirectoryByPath(java.io.File rootDirectory, java.io.File currentDirectory, String path) throws NoSuchDirectoryException {
		try {
			java.io.File targetFile = Utility._getFileByPath(rootDirectory, currentDirectory, path);
			if (!targetFile.isDirectory())
				throw new NoSuchFileException(path);
			return targetFile;
		} catch (NoSuchFileException nsfe) {
			throw new NoSuchDirectoryException(path);
		}
	}

	private static java.io.File _getFileByPath(java.io.File rootDirectory, java.io.File currentDirectory, String path) throws NoSuchFileException {
		java.io.File workingDirectory = null;
		if (path.startsWith(RemoteFile.rootDirectoryNotation)) {
			workingDirectory = rootDirectory;
		} else {
			workingDirectory = currentDirectory;
		}

		StringTokenizer st = new StringTokenizer(path, RemoteFile.pathSeperator);
		while (st.hasMoreTokens()) {
			String p = st.nextToken();

			if (p.equals(RemoteFile.parentDirectoryNotation)) {
				if (workingDirectory != rootDirectory) {
					workingDirectory = workingDirectory.getParentFile();
				}
				continue;
			} else if (p.equals(RemoteFile.currentDirectoryNotation)) {
				continue;
			}

			boolean found = false;
			for (java.io.File f : workingDirectory.listFiles()) {
				if (f.getName().equals(p) && !st.hasMoreTokens())
					return f;
				if (f.getName().equals(p) && st.hasMoreTokens() && f.isDirectory()) {
					workingDirectory = f;
					found = true;
					break;
				}
			}
			if (!found) {
				throw new NoSuchFileException(path);
			}
		}

		/* never reachable */
		return workingDirectory;
	}
}
